<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0">
    <title>多级地址联动</title>
    <script src="https://cdn.staticfile.org/jquery/3.4.1/jquery.js"></script>
    <link rel="stylesheet"
          href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.css">
    <script src="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/js/bootstrap.js"></script>
    <script src="./tmpl.js"></script>
    <style>
        .city-title ul {
            border-bottom: 2px solid #5270aa;
            padding: 0;
            overflow: hidden;
        }

        .city-title li.active {
            border-bottom-color: transparent;
            background: #5270aa;
            color: #fff;
        }

        .city-title li {
            float: left;
            width: 33.33%;
            height: 40px;
            line-height: 40px;
            text-align: center;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            cursor: pointer;
            padding: 0 5px;
        }

        .city-area {
            max-width: 600px;
        }

        .city-area>.tab-pane {
            display: none;
        }

        .city-area>.tab-pane.active {
            display: block;

        }

        .attr-list-body {
            padding: 5px 20px;
        }

        .attr-list-body label {
            margin: 0 10px;
            padding: 5px;
        }

        .attr-list-body label.active {
            color: white;
            background-color: #4c72d5;
            border-radius: 3px;
        }

        .attr-bar {
            text-align: right;
            padding: 0 10px 10px 0;
        }

        .btn {
            border-radius: 5px;
            line-height: 24px;
            padding: 5px;
            margin-right: 15px
        }

        .btn.blue-btn {
            background-color: #4c72d5;
            border: 1px solid #4c72d5;
            color: #fff;
        }

        .btn.gray-btn {
            background-color: #ddd;
            border: 1px solid #ddd;
            color: #000;
        }

        .btn.btn-small {
            width: 50px;
        }
    </style>
</head>
<input type="text"
       name='idNumber'
       id='idNumber'>
<br>
<input type="radio"
       name='sex'>男
<input type="radio"
       name='sex'>女
<br>
<input type="date"
       name='birthDay'
       id='birthDay'>
<br>
<div id="domicile">
</div>
<div id="nowAddress">
</div>
<script id="childNodeListTemplate"
        type="x-tmpl">
        {% for(var i = 0; i< o.length; i++){ %}
            <label nodeid="{%= o[i].id %}"  title="{%= o[i].text %}">{%= o[i].text %}</label>
        {% } %}
</script>

<body>
    <script src="./area.js"></script>
    <script>
        var addressOption = {
                'elem': ['domicile', 'nowAddress'],//HTMLID容器
                'tmpl': 'childNodeListTemplate',//选择模板
                'addressArr': addressArr,//渲染数据
                // 'data': ['150623', '440111'],//身份证号码回填值
                // 'selectArr': ['domicile','nowAddress'],//设置hiddeninputname
                'callback': doSearch //点击确定回调函数获取当前选中值（广东省 > 广州市 > 花都区）
            }


        $(function () {
            initAreaTree(addressOption);
            initEvent();
        })



        function initEvent() {
            $("#idNumber").on("keyup blur", function () {
                var $this = $(this);
                if ($this.val().length == 18) {
                    //获取生日
                    var isCardTrue = isCardID($this.val());
                    if (isCardTrue != true) {
                        alert(isCardTrue);
                    } else {
                        var birthDay = $this.val().substr(6, 8);
                        var sex = $this.val().charAt(16);
                        var $sexRadio = $("input[name = 'sex']");
                        var permanentAddress = $this.val().substr(0, 6);
                        //身份证格式正确自动回填出生日期
                        $("#birthDay").val(birthDay.substring(0, 4) + '-' + birthDay.substring(4, 6) + '-' + birthDay.substring(6, 8));
                        //身份证格式正确自动回填性别
                        if (parseInt(sex) % 2 == 0) {
                            $sexRadio.eq(1).prop("checked", true);
                        } else {
                            $sexRadio.eq(0).prop("checked", true);
                        }
                        $('.dropdown').remove();
                        //身份证格式正确自动回填户籍地址
                        addressOption.data = [permanentAddress, ""];
                        initAreaTree(addressOption);
                    }
                }

            })
        }


        function isCardID(sId) {
            //判断身份证号
            var aCity = {
                11: "北京", 12: "天津", 13: "河北", 14: "山西", 15: "内蒙古",
                21: "辽宁", 22: "吉林", 23: "黑龙江", 31: "上海", 32: "江苏",
                33: "浙江", 34: "安徽", 35: "福建", 36: "江西", 37: "山东",
                41: "河南", 42: "湖北", 43: "湖南", 44: "广东", 45: "广西",
                46: "海南", 50: "重庆", 51: "四川", 52: "贵州", 53: "云南",
                54: "西藏", 61: "陕西", 62: "甘肃", 63: "青海", 64: "宁夏",
                65: "新疆", 71: "台湾", 81: "香港", 82: "澳门", 91: "国外"
            }
            var iSum = 0;
            var info = "";
            if (!/^\d{17}(\d|x)$/i.test(sId)) return "身份证长度或格式错误";
            sId = sId.replace(/x$/i, "a");
            if (aCity[parseInt(sId.substr(0, 2))] == null) return "身份证地区非法";
            sBirthday = sId.substr(6, 4) + "-" + Number(sId.substr(10, 2)) + "-" + Number(sId.substr(12, 2));
            var d = new Date(sBirthday.replace(/-/g, "/"));
            if (sBirthday != (d.getFullYear() + "-" + (d.getMonth() + 1) + "-" + d.getDate())) return "身份证出生日期非法";
            for (var i = 17; i >= 0; i--) iSum += (Math.pow(2, i) % 11) * parseInt(sId.charAt(17 - i), 11);
            if (iSum % 11 != 1) return "身份证号非法";
            return true;
        }

        function doSearch(data) {
            console.log(data);
        }
        //*************省市区start***************//
        /**
         * 地址树的初始化、回填和操作
         * @param {array} elem HTMLID容器
         * @param {string} tmpl 选择模板
         * @param {array} addressArr 渲染数据
         * @param {array} data 回填值
         * @param {array} selectArr 获取值的input的name
         * @param {function} callback 点击确定回调函数获取当前选中值（广东省 > 广州市 > 花都区）
         */
        function initAreaTree(options) {
            var $addressWrap = options.elem;
            var addressTmpl = options.tmpl;
            var curNode = options.data;
            var selectArr = options.selectArr;
            var addressArr = options.addressArr;
            var curAreaVal = '';
            if (!selectArr) {
                selectArr = $addressWrap
            }
            $.each($addressWrap, function (i, n) {
                var areaHtml = '<div class="tree-wrap dropdown">' +
                    '<div class="dropdown-toggle" data-toggle="dropdown">' +
                    '<span class="selectedArea">请选择 </span>' +
                    '<input type="hidden" name="' + selectArr[i] + '" value="">' +
                    '<span class="glyphicon glyphicon-chevron-down" style="vertical-align:middle;margin-left: 5px;"></span>' +
                    '</div>' +
                    '<div class="dropdown-menu">' +
                    '<div class="city-title">' +
                    '<ul>' +
                    '<li ref=".city" class="active" defaultName="省份">省份</li>' +
                    '<li class="hide" ref=".area" defaultName="地市">地市</li>' +
                    '<li class="hide" ref=".station" defaultName="区县">区县</li>' +
                    '</ul>' +
                    '</div>' +
                    '<div class="city-area">' +
                    '<div class="tab-pane active city">' +
                    '<dl class="attr-list">' +
                    '<dd class="attr-list-body ' + n + '" >' +
                    '</dd>' +
                    '</dl>' +
                    '</div>' +
                    '<div class="tab-pane area">' +
                    '<dl class="attr-list">' +
                    '<dd class="attr-list-body">' +
                    '</dd>' +
                    '</dl>' +
                    '</div>' +
                    '<div class="tab-pane station">' +
                    '<dl class="attr-list">' +
                    '<dd class="attr-list-body">' +
                    '</dd>' +
                    '</dl>' +
                    '</div>' +
                    '<div class="attr-bar"><a class="btn btn-small blue-btn attrSureBtn mr10">确定</a><a class="btn btn-small gray-btn attrCancelBtn">清除</a></div>' +
                    '</div>' +
                    '</div>' +
                    '</div>';
                $("#" + n).append(areaHtml);
                $("." + n).html(tmpl(addressTmpl, addressArr));

                //数据回填
                if (curNode) {
                    var curNodeId = typeof (curNode[i]) !== 'undefined' ? curNode[i] : '';
                    var j = 2;
                    while (j < curNodeId.length + 2) {
                        var nodeSubStr = curNodeId.substring(0, j);
                        var curLable = $("#" + n).find(".city-area label[nodeid='" + nodeSubStr + "']");
                        selectCurArea(addressArr, curLable, n);
                        j = j + 2;
                    }
                }
            });

            $('.city-title li').click(function (event) {
                selectCurCity($(this));
                var height = $(this).parents(".dropdown-menu").height();
                var width = $(this).parents(".dropdown-menu").width();
                var $addressWrap = $(this).parents('.filter-tag');
                event.stopPropagation();
            });

            $(".tree-wrap").on("click", ".city-area label", function (event) {
                var id = $(this).parents(".tree-wrap").parent().attr("id");
                curAreaVal = selectCurArea(addressArr, $(this), id);
                event.stopPropagation();
            });

            $(".tree-wrap").on("click", ".city-area", function (event) {
                event.stopPropagation();
            });

            $(".attrSureBtn").click(function () {
                if (options.callback) {
                    options.callback(curAreaVal);
                }
                $('.dropdown-menu').click();
            });

            $(".attrCancelBtn").click(function () {
                var $treeWrap = $(this).parents('.tree-wrap');
                $treeWrap.find(".selectedArea").html("请选择");
                $treeWrap.find("input").val("");
                $.each($treeWrap.find("li"), function (i, n) {
                    if (i == 0) {
                        $(n).addClass("active");
                    } else {
                        $(n).addClass("hide").removeClass("active");
                    }
                    $(n).html($(n).attr("defaultname"));
                });
                $treeWrap.find("label").removeClass("active");
                $treeWrap.find(".city-title li:first").click();
                $('.dropdown-menu').click();
            });


            $(".tree-wrap .dropdown-toggle").click(function () {
                if ($(this).closest('.form-control').attr('readonly')) { //如果控件禁止编辑，就不做处理；
                    $(this).removeAttr('data-toggle').css('cursor', 'not-allowed');
                    return;
                }
                var height = $(this).next().height();
                var width = $(this).next().width();
                var $curAddressWrap = $(this).parents('.filter-tag');
            })

        }
        /**
         * 查询某区域下的下级行政树
         * @param {obj} addressArr 地址树数据
         * @param {string} nodeId 某个地址的id
         * @return {obj} 返回属于某个地址的下级行政树
         */
        function queryChildNodes(addressArr, nodeId) {
            var nodeList = [];
            var nodeSubStr = nodeId.substring(0, 2);
            $.each(addressArr, function (i, n) {
                if (nodeSubStr == n.id) {
                    nodeList = n.ChildNodes;
                    if (nodeId.length > 2) {
                        $.each(n.ChildNodes, function (index, obj) {
                            if (nodeId == obj.id) {
                                nodeList = obj.ChildNodes;
                                return false;
                            }
                        })
                    }
                    return false;
                }
            });
            return nodeList;
        }
        /**
         * 获取选中的地址
         * @param {obj} addressArr 地址树数据
         * @param {string} $this 具体某个地点jQuery元素
         * @param {string} id 地址树包裹层的id
         * @return {obj} 返回当前选中的地址区域
         */
        function selectCurArea(addressArr, $this, id) {
            var $curTitleLi = $this.parents(".dropdown-menu").find(".city-title li.active");
            var $cityTitleLi = $this.parents(".dropdown-menu").find(".city-title li");
            var NODE_ID = $this.attr("nodeid");
            var area = '';
            var len = $cityTitleLi.length;
            var $selectedArea = $this.parents(".tree-wrap").find(".selectedArea");

            $curTitleLi.html($this.html());

            $cityTitleLi.each(function (i) {
                area += $(this).text();
                if ($(this).hasClass("active")) {
                    return false;
                }
                if (i != (len - 1)) {
                    area += ' > ';
                }
            });

            $selectedArea.html(area);
            $selectedArea.next().val(NODE_ID);
            var curAreaVal = area;

            if ($curTitleLi.next().length != 0) {

                $curTitleLi.nextAll().each(function () {
                    $(this).html($(this).attr("defaultName"));
                });
                $curTitleLi.next().removeClass("hide");
                selectCurCity($curTitleLi.next());//点击后，active的li就改变了，要重新选择
                $curTitleLi = $this.parents(".dropdown-menu").find(".city-title li.active");

                var nodeList = queryChildNodes(addressArr, NODE_ID);

                $("#" + id + " " + $curTitleLi.attr("ref")).find("dd").html(tmpl("childNodeListTemplate", nodeList));

            }

            $this.addClass("active").siblings().removeClass("active");
            return curAreaVal;
        }

        /**
         * tab切换行政区域内容
         * @param {string} $this 下个tab的jQuery元素
         */
        function selectCurCity($this) {
            if (!$this.hasClass("disable")) {
                var ref = $this.attr('ref');
                var $cityArea = $this.parents(".city-title").next();

                $this.addClass('active').siblings().removeClass('active');
                $cityArea.find('.tab-pane').removeClass('active');
                $cityArea.find(ref).addClass('active');
            }
        }

//*************省市区end***************//
    </script>
</body>

</html>